/**
 * Hook-Fetch Request Wrapper Type Definitions
 * 
 * This file contains type definitions for the hook-fetch wrapper implementation
 * that maintains compatibility with existing axios-based patterns while leveraging
 * hook-fetch's modern architecture.
 */

import type { HookFetchPlugin } from 'hook-fetch';

// ============================================================================
// Core Response and Request Types
// ============================================================================

/**
 * Standard HTTP response interface that maintains compatibility with existing API patterns
 * This matches the structure expected by the current application services
 */
export interface IHttpResponse<T = any> {
  /** Response status code (200 for success, other codes for various error states) */
  code: number;
  /** Response data payload */
  data: T;
  /** Response message (success message or error description) */
  msg: string;
  /** Optional array data for list responses */
  rows?: T[];
}

/**
 * Generic object interface for flexible key-value structures
 * Used for request parameters, headers, and other dynamic objects
 */
export interface IObject<T = any> {
  [key: string]: T;
}

/**
 * Request configuration interface for internal request handling
 * Provides a unified structure for all HTTP request configurations
 */
export interface RequestConfig {
  /** Request URL path */
  url: string;
  /** HTTP method */
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  /** Query parameters for GET requests or URL parameters */
  params?: IObject;
  /** Request body data for POST/PUT requests */
  data?: IObject;
  /** Custom headers for the request */
  headers?: IObject;
  /** Expected response type */
  responseType?: 'json' | 'blob';
  /** Request timeout in milliseconds */
  timeout?: number;
}

// ============================================================================
// Plugin-Specific Types
// ============================================================================

/**
 * Authentication plugin configuration
 * Handles automatic token injection and authentication headers
 */
export interface AuthPluginConfig {
  /** Function to retrieve current authentication token */
  getToken?: () => string | null;
  /** Function to retrieve current locale for Accept-Language header */
  getLocale?: () => string;
  /** Whether to add timestamp to GET requests to prevent caching */
  addTimestamp?: boolean;
}

/**
 * Error handling plugin configuration
 * Manages HTTP status codes and business logic error handling
 */
export interface ErrorHandlingPluginConfig {
  /** Function to handle login redirects on authentication errors */
  redirectLogin?: () => void;
  /** Custom error message mapping for HTTP status codes */
  errorMessages?: Record<number, string>;
  /** Whether to log errors to console */
  enableLogging?: boolean;
}

/**
 * Request deduplication plugin configuration
 * Prevents duplicate simultaneous requests
 */
export interface DeduplicationPluginConfig {
  /** Custom function to generate request identifiers */
  getRequestKey?: (config: RequestConfig) => string;
  /** Error code to return for duplicate requests */
  duplicateErrorCode?: string;
}

/**
 * Combined plugin configuration interface
 */
export interface PluginConfigurations {
  auth?: AuthPluginConfig;
  errorHandling?: ErrorHandlingPluginConfig;
  deduplication?: DeduplicationPluginConfig;
}

// ============================================================================
// Wrapper and Service Types
// ============================================================================

/**
 * Hook-fetch wrapper configuration
 * Configuration options for the hook-fetch wrapper instance
 */
export interface HookFetchWrapperConfig {
  /** Base URL for all requests */
  baseURL: string;
  /** Default timeout for requests */
  timeout?: number;
  /** Default headers to include with all requests */
  headers?: Record<string, string>;
  /** Plugin configurations */
  pluginConfigs?: PluginConfigurations;
}

/**
 * Request method type for download operations
 */
export type RequestMethod = 'GET' | 'POST';

/**
 * File download configuration
 */
export interface DownloadConfig {
  /** Download method (GET or POST) */
  method?: RequestMethod;
  /** Request parameters */
  params?: IObject;
  /** Request headers */
  headers?: IObject;
  /** Filename for the downloaded file */
  filename?: string;
}

// ============================================================================
// Service Interface Types
// ============================================================================

/**
 * Base service interface that maintains compatibility with existing service patterns
 * This interface ensures the new hook-fetch implementation can be a drop-in replacement
 */
export interface IBaseService {
  /**
   * Perform GET request
   * @param path - API endpoint path
   * @param params - Query parameters
   * @param headers - Custom headers
   */
  get<T = any>(path: string, params?: IObject, headers?: IObject): Promise<IHttpResponse<T>>;

  /**
   * Perform POST request
   * @param path - API endpoint path
   * @param body - Request body data
   * @param headers - Custom headers
   */
  post<T = any>(path: string, body?: IObject, headers?: IObject): Promise<IHttpResponse<T>>;

  /**
   * Perform PUT request
   * @param path - API endpoint path
   * @param params - Request parameters
   * @param headers - Custom headers
   */
  put<T = any>(path: string, params?: IObject, headers?: IObject): Promise<IHttpResponse<T>>;

  /**
   * Perform DELETE request
   * @param path - API endpoint path
   * @param params - Request parameters
   */
  delete<T = any>(path: string, params: IObject): Promise<IHttpResponse<T>>;

  /**
   * Download file from API endpoint
   * @param path - API endpoint path
   * @param params - Request parameters
   * @param filename - Optional filename for download
   * @param method - HTTP method (GET or POST)
   */
  download(path: string, params?: IObject, filename?: string, method?: RequestMethod): Promise<IHttpResponse>;

  /**
   * Download file from direct URL
   * @param url - Direct file URL
   * @param filename - Filename for download
   */
  downloadFile(url: string, filename: string): Promise<void>;
}

// ============================================================================
// Plugin Factory Types
// ============================================================================

/**
 * Authentication plugin factory function type
 */
export type AuthPluginFactory = (config?: AuthPluginConfig) => HookFetchPlugin<IHttpResponse>;

/**
 * Error handling plugin factory function type
 */
export type ErrorHandlingPluginFactory = (config?: ErrorHandlingPluginConfig) => HookFetchPlugin<IHttpResponse>;

/**
 * Request deduplication plugin factory function type
 */
export type DeduplicationPluginFactory = (config?: DeduplicationPluginConfig) => HookFetchPlugin<IHttpResponse>;

// ============================================================================
// Utility Types
// ============================================================================

/**
 * Pending request tracking interface
 */
export interface PendingRequest {
  /** Request identifier */
  key: string;
  /** Request promise */
  promise: Promise<any>;
  /** Request timestamp */
  timestamp: number;
}

/**
 * HTTP status code error mapping
 */
export interface HttpErrorMessages {
  400: string; // Bad Request
  401: string; // Unauthorized
  403: string; // Forbidden
  404: string; // Not Found
  408: string; // Request Timeout
  500: string; // Internal Server Error
  501: string; // Not Implemented
  502: string; // Bad Gateway
  503: string; // Service Unavailable
  504: string; // Gateway Timeout
  505: string; // HTTP Version Not Supported
}

/**
 * Default HTTP error messages (Chinese)
 */
export const DEFAULT_HTTP_ERROR_MESSAGES: HttpErrorMessages = {
  400: '请求参数错误',
  401: '未授权，请登录',
  403: '拒绝访问',
  404: '请求地址出错',
  408: '请求超时',
  500: 'API接口报500错误',
  501: '服务未实现',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时',
  505: 'HTTP版本不受支持',
};

// ============================================================================
// Compatibility Types
// ============================================================================

/**
 * Legacy axios-style response interface for backward compatibility
 * This ensures existing code that expects axios response structure continues to work
 */
export interface AxiosCompatibleResponse<T = any> {
  data: IHttpResponse<T>;
  status: number;
  statusText: string;
  headers: Record<string, string>;
  config: RequestConfig;
}

/**
 * Type guard to check if response is in expected IHttpResponse format
 */
export function isIHttpResponse<T = any>(response: any): response is IHttpResponse<T> {
  return (
    typeof response === 'object' &&
    response !== null &&
    typeof response.code === 'number' &&
    typeof response.msg === 'string' &&
    'data' in response
  );
}

/**
 * Type utility to extract data type from IHttpResponse
 */
export type ExtractResponseData<T> = T extends IHttpResponse<infer U> ? U : never;